package com.xk.user.service;

import com.hy.common.enums.ExceptionEnums;
import com.hy.common.exception.XkException;
import com.hy.common.utils.CodecUtils;
import com.xk.user.mapper.UserMapper;
import com.xk.user.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserService {
    /**
     * 校验数据
     * @param data
     * @param type
     * @return
     */
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final String KEY_PREFIX="xk.sms";
    private static final String PHONE_XL="xk.phone";
    private static final long SMS_MIN_TIME=180000;//时长为五分钟

    public Boolean checkData(String data, Integer type) {
        User user = new User();
        //判断是用户名/手机
        switch (type){
            case 1:
                user.setUsername(data);
                break;
            case 2:
                user.setPhone(data);
                break;
            default :
                throw new XkException(ExceptionEnums.INVALID_USER_DATA_TYPE);
        }
        int i = userMapper.selectCount(user);
        //校验用户名是否存在
        return i==0;
    }

    /**
     * 发送短信验证码
     * @param phone
     */
    public void sendSms(String phone) {
        //按照手机号码限流
        String slKey=PHONE_XL+phone;
        String lastTime = redisTemplate.opsForValue().get(slKey);
        if (StringUtils.isNoneBlank(lastTime)){//不为null
            Long last = Long.valueOf(lastTime);
            if (System.currentTimeMillis()-last<SMS_MIN_TIME){//小于3分钟就阻止发送消息
                log.info("验证码发送过于频繁");
                throw new XkException(ExceptionEnums.SEND_SMS_FAIL);

            }
        }
        //===================================
        String key=KEY_PREFIX+phone;
        //生成六位随机的验证码
        String code="";
        Random rand=new Random();
        for(int a=0;a<6;a++){
            code+=rand.nextInt(10);//0-9的自然数
        }
        //发送消息
        Map<String, String> msg = new HashMap<>();
        msg.put("phone",phone);
        msg.put("code",code);
        amqpTemplate.convertAndSend("xk.sms.exchange","sms.verify.code",msg);
        //消息发送完成，将验证码保存到redis中，校验的时候从redis中获得即可,设置验证码5分钟有效
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);

        /*根据手机号码限流，发送短信成功后写入到redis中,key就是电话号码，value是当前时间,
        并设置3分钟后自动删除*/
        redisTemplate.opsForValue().set(slKey,String.valueOf(System.currentTimeMillis()),
                3, TimeUnit.MINUTES);
    }

    /**
     * 用户注册
     * @param user
     * @param code
     */
    public void register(User user, String code) throws UnsupportedEncodingException {
        String key=KEY_PREFIX+user.getPhone();
        //检验验证码是否正确,从redis中得到验证码
        String codeCache = redisTemplate.opsForValue().get(key);
        if (!codeCache.equals(code)){//验证码不存在
            throw new XkException(ExceptionEnums.CODE_NOT_FOND);

        }
        //生成盐，工具中使用的是uuid生成的
        String salt= CodecUtils.generateSalt();
        user.setSalt(salt);//将盐值也写入到数据库中
        user.setCreated(new Date());
        String password = CodecUtils.md5Hex(user.getPassword(), salt);
        user.setPassword(password);
        //写入数据库
        userMapper.insert(user);
    }

    /**
     * 根据用户名或密码查询用户
     * @param username
     * @param password
     * @return
     */
    public User queryUserBynameAndPwd(String username,String password) {
        User user=new User();
        //查询用户
        user.setUsername(username);
        User u = userMapper.selectOne(user);
        if (u==null){
            throw new RuntimeException();
        }
        //校验密码
        if (!StringUtils.equals(u.getPassword(),CodecUtils.md5Hex(password,u.getSalt()))){
            throw new XkException(ExceptionEnums.INVALID_USERNAME_PASSWORD);
        }
        //用户名和密码正确
        return u;
    }
}
